#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonArray>
#include <QTime>

#include <opencv2/opencv.hpp>
#include <qdatetime.h>
#include <qglobal.h>
#include <vector>

#include "ward-http-server.h"
#include "ai_recognition.h"

WardHttpServer::WardHttpServer(QObject *parent) : QTcpServer(parent), _in_multipart(false) {}

void WardHttpServer::incomingConnection(qintptr socketDescriptor) {
    QTcpSocket* client = new QTcpSocket(this);
    client->setSocketDescriptor(socketDescriptor);
    connect(client, &QTcpSocket::readyRead, this, &WardHttpServer::handleRequest);
}

QByteArray WardHttpServer::extractBoundary(const QByteArray& request) {
    // 提取boundary值
    QByteArray contentType = request.mid(request.indexOf("Content-Type: multipart/form-data"));
    int boundaryPos = contentType.indexOf("boundary=") + 9;
    int boundaryEnd = contentType.indexOf("\r\n");
    QByteArray boundary = contentType.mid(boundaryPos, boundaryEnd - boundaryPos);
    // qDebug() << "contentType: " << contentType;
    // qDebug() << "extractBoundary: " << boundary;
    return "--" + boundary;
}

void WardHttpServer::sendResponse(QTcpSocket* client, int status, const QByteArray& content) {
    QByteArray response;
    response.append("HTTP/1.1 " + QByteArray::number(status) + " OK\r\n");
    response.append("Content-Type: application/json\r\n");
    response.append("Content-Length: " + QByteArray::number(content.size()) + "\r\n");
    response.append("Access-Control-Allow-Origin: *\r\n");  // 允许所有域访问
    response.append("\r\n");
    response.append(content);

    // qDebug() << "#####http server sendResponse: ";
    // qDebug() << response;
    client->write(response);
    client->disconnectFromHost();
}

QByteArray WardHttpServer::processMultipartData(const QByteArray& request) {
    QByteArray boundaryEnd = _boundary + "--\r\n";
    int start = _buffer.indexOf(_boundary + "\r\n");
    if (start == -1) {
        qErrnoWarning("[Multipart] Start boundary not found.");
        return {};
    }

    int headerStart = start + _boundary.length() + 2;
    int headerEnd = _buffer.indexOf("\r\n\r\n", headerStart);
    if (headerEnd == -1) {
        qErrnoWarning("[Multipart] Header end not found.");
        return {};
    }

    int fileStart = headerEnd + 4;
    int fileEnd = _buffer.indexOf(boundaryEnd, fileStart);
    if (fileEnd == -1) {
        qErrnoWarning("[Multipart] File end not found.");
        return {};
    }

    return _buffer.mid(fileStart, fileEnd - fileStart);
}

QByteArray WardHttpServer::GetSubtitles(QDateTime start_time, QDateTime end_time) {
    QList<SubtitleItem> audioRecognitions = AIRecogManager::getInstance().getAudioRecognitions(start_time, end_time);
    
    // 创建字幕数据数组
    QJsonArray subtitles;

    // 遍历音频识别数据并创建字幕对象
    for (const SubtitleItem& audioRecognition : audioRecognitions) {
        QJsonObject subtitle;
        
        // 这里使用音频识别的时间戳和文本
        subtitle["time"] = audioRecognition.timestamp.toString("yyyy-MM-dd hh:mm:ss.zzz");  // 时间戳
        subtitle["text"] = audioRecognition.content;    // 字幕内容
        
        // 将字幕对象添加到字幕数组
        subtitles.append(subtitle);
    }

    // 创建最终的响应 JSON
    QJsonObject response;
    response["subtitles"] = subtitles;

    // 将 JSON 响应转化为 QByteArray
    QByteArray responseData = QJsonDocument(response).toJson();

    return responseData;
}


void WardHttpServer::handleRequest() {
    QTcpSocket* client = qobject_cast<QTcpSocket*>(sender());

    // 解析HTTP请求
    QByteArray request = client->readAll();

    qDebug() << "New request from " << client->peerAddress().toString();
    qDebug() << "#####request: \n" << request << '\n';

    // HEAD
    // ------boundary\r\ninfoxx
    // xxxxxxxxxxxxxxxxxxxxxxxx
    // xxxxxxxxxxxxxxxxxxxxxxxx
    // xxxxxxxxxxxxxxxxxxxxxxxx
    // xxxxxxxxxxxxxxxxxxxxxxxx
    // xxxx------boundary--\r\n

    if (_in_multipart) {
        _buffer.append(request);
        // qDebug() << "@@@@@append buffer";
        // end boundary
        if (_buffer.contains(_boundary + "--\r\n")) {
            QByteArray image_data = processMultipartData(_buffer);
            // qDebug() << "@@@@@all data received";
            QByteArray response = processImage(image_data);  // 使用完整的数据进行处理

            // qDebug() << "#####image_data: " << image_data;
            sendResponse(client, 200, response);
            _in_multipart = false;
            _buffer.clear();
        }
    }

    // *******************************************************************

    // 处理POST请求 head
    if (request.startsWith("POST /detect") &&
        request.contains("Content-Type: multipart/form-data")) {
        // 检查是否为 multipart/form-data 请求, head部分
        _in_multipart = true;
        _boundary = extractBoundary(request);
        _buffer.clear();  // 清空之前的缓冲区
    } else if (request.startsWith("POST /get_subtitles")) {
        qDebug() << "deal with `get_subtitles`";

        QByteArray body = request.mid(request.indexOf("\r\n\r\n", 1));

        // 提取 JSON 请求体中的 last_timestamp
        QJsonDocument doc = QJsonDocument::fromJson(body);
        if (!doc.isObject()) {
            qDebug() << "Invalid JSON format in request body";
            sendResponse(client, 400, "Invalid JSON format");
            return;
        }

        QJsonObject jsonObject = doc.object();
        QString start_time_str = jsonObject["start"].toString();
        QString end_time_str = jsonObject["end"].toString();
        QDateTime start_time = QDateTime::fromString(start_time_str, "yyyy-MM-ddThh:mm:ss.zzzZ");
        QDateTime end_time = QDateTime::fromString(end_time_str, "yyyy-MM-ddThh:mm:ss.zzzZ");

        QByteArray response = GetSubtitles(start_time, end_time);

        sendResponse(client, 200, response);
    } else if (request.startsWith("OPTIONS")) {

        qDebug() << "deal with `OPTIONS`";
        QByteArray response = "HTTP/1.1 200 OK\r\n";
        response.append("Access-Control-Allow-Origin: *\r\n"); // 允许所有来源
        response.append("Access-Control-Allow-Methods: POST, GET, OPTIONS\r\n"); // 允许的 HTTP 方法
        response.append("Access-Control-Allow-Headers: Content-Type\r\n"); // 允许的请求头
        response.append("\r\n");  // 结束头部
        client->write(response);
        client->disconnectFromHost();
    } else {
        // // 其他类型请求的响应
        // QByteArray response = "HTTP/1.1 200 OK\r\n";
        // response.append("Access-Control-Allow-Origin: *\r\n");  // 允许所有域访问
        // response.append("\r\n");
        // client->write(response);
        // client->disconnectFromHost();
    }
}

QByteArray WardHttpServer::processImage(const QByteArray& imageData) {
    try {
        qDebug() << "Received image data size:" << imageData.size();
        std::vector<DL_RESULT> results;
        // 解码图片
        cv::Mat input = cv::imdecode(
            cv::Mat(1, imageData.size(), CV_8UC1, (void*)imageData.data()), 
            cv::IMREAD_COLOR
        );
        
        if(input.empty()) throw std::runtime_error("Invalid image data");

        MatWrapper wrapper = {input, 0};
        // CUDA处理
        results = CudaManager::getInstance().processWithCuda(wrapper);
        
        // 转换为JSON
        QJsonArray detections;
        for(const auto& res : results) {
            QJsonObject bbox;
            bbox["x"] = res.box.x;
            bbox["y"] = res.box.y;
            bbox["width"] = res.box.width;
            bbox["height"] = res.box.height;

            QJsonObject obj;
            obj["bbox"] = bbox;
            obj["class_name"] = res.classId;
            obj["color"] = "#00FF00";
            obj["confidence"] = res.confidence;
            obj["frame_width"] = input.cols;
            obj["frame_height"] = input.rows;

            detections.append(obj);
        }

        QJsonObject jsonResults;
        jsonResults["detections"] = detections;

        return QJsonDocument(jsonResults).toJson();
    } catch(const std::exception& e) {
        QJsonObject error;
        error["error"] = QString(e.what());
        return QJsonDocument(error).toJson();
    }
}

HttpServerThread::HttpServerThread(QObject *parent) : QThread(parent) {}

HttpServerThread::~HttpServerThread() {
    delete httpServer;
}

void HttpServerThread::run() {
    httpServer = new WardHttpServer();
    httpServer->moveToThread(this);

    if (!httpServer->listen(QHostAddress::LocalHost, 5000)) {
        qCritical() << "HTTP server failed to start!";
        return;
    }
    exec();  // 启动线程事件循环
}
